home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / System / XADmaster / xad_dev / Sources / clients / LZX.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-04-01  |  25.0 KB  |  957 lines

  1. #ifndef XADMASTER_LZX_C
  2. #define XADMASTER_LZX_C
  3.  
  4. /* Programmheader
  5.  
  6.     Name:        LZX.c
  7.     Main:        xadmaster
  8.     Versionstring:    $VER: LZX.c 1.7 (02.10.2000)
  9.     Author:        SDI, David Tritscher
  10.     Distribution:    Freeware
  11.     Description:    LZX file archiver client
  12.  
  13.  1.0   09.02.99 : first working version
  14.  1.1   13.03.99 : now uses register parameters
  15.  1.2   20.06.99 : removed exec.library calls
  16.  1.3   29.06.99 : now uses master free stuff
  17.  1.4   29.08.99 : uses ConvertE.c instead of own routines and
  18.     uses crc copy function
  19.  1.5   02.01.00 : now library version 4 client
  20.  1.6   09.03.00 : now library version 6 client
  21.  1.7   02.10.00 : added check for different CPU's
  22. */
  23.  
  24. /* The decrunch routines of this client are based on unlzx sources code made
  25.    by David Tritscher. Thanks guy, was a big help. I made the routines
  26.    reentrant (using a parameter structure) and developed the XAD interface
  27.    functions. */
  28.  
  29. #include <proto/xadmaster.h>
  30. #include <exec/memory.h>
  31. #include <dos/dos.h>
  32. #include "SDI_compiler.h"
  33. #define SDI_TO_ANSI
  34. #include "SDI_ASM_STD_protos.h"
  35. #include "ConvertE.c"
  36. #include "xadCPU.h"
  37.  
  38. #ifndef XADMASTERFILE
  39. #define LZX_Client        FirstClient
  40. #define NEXTCLIENT        0
  41. #define XADMASTERVERSION    8
  42. UBYTE version[] = "$VER: LZX 1.7 (02.10.2000)" CPUTEXT " Freeware by Dirk Stöcker";
  43. #endif
  44. #define LZX_VERSION        1
  45. #define LZX_REVISION        7
  46.  
  47. /* ---------------------------------------------------------------------- */
  48.  
  49. #define LZXINFO_DAMAGE_PROTECT 1
  50. #define LZXINFO_FLAG_LOCKED 2
  51.  
  52. struct LZXInfo_Header
  53. {
  54.   UBYTE ID[3];            /* "LZX" */
  55.   UBYTE Flags;            /* LZXINFO_FLAG_#? */
  56.   UBYTE Unknown[6];        
  57. };
  58.  
  59. #define LZXHDR_FLAG_MERGED    (1<<0)
  60.  
  61. #define LZXHDR_PROT_READ    (1<<0)
  62. #define LZXHDR_PROT_WRITE    (1<<1)
  63. #define LZXHDR_PROT_DELETE    (1<<2)
  64. #define LZXHDR_PROT_EXECUTE    (1<<3)
  65. #define LZXHDR_PROT_ARCHIVE    (1<<4)
  66. #define LZXHDR_PROT_HOLD    (1<<5)
  67. #define LZXHDR_PROT_SCRIPT    (1<<6)
  68. #define LZXHDR_PROT_PURE    (1<<7)
  69.  
  70. #define LZXHDR_TYPE_MSDOS    0
  71. #define LZXHDR_TYPE_WINDOWS    1
  72. #define LZXHDR_TYPE_OS2        2
  73. #define LZXHDR_TYPE_AMIGA    10
  74. #define LZXHDR_TYPE_UNIX    20
  75.  
  76. #define LZXHDR_PACK_STORE    0
  77. #define LZXHDR_PACK_NORMAL    2
  78. #define LZXHDR_PACK_EOF        32
  79.  
  80. struct LZXArc_Header
  81. {
  82.   UBYTE Attributes;        /*  0 - LZXHDR_PROT_#? */
  83.   UBYTE pad1;            /*  1 */
  84.   ULONG FileSize;        /*  2 (little endian) */
  85.   ULONG CrSize;            /*  6 (little endian) */
  86.   UBYTE MachineType;        /* 10 - LZXHDR_TYPE_#? */
  87.   UBYTE PackMode;        /* 11 - LZXHDR_PACK_#? */
  88.   UBYTE Flags;            /* 12 - LZXHDR_FLAG_#? */
  89.   UBYTE pad2;            /* 13 */
  90.   UBYTE CommentSize;        /* 14 - length (0-79) */
  91.   UBYTE ExtractVersion;        /* 15 - version needed to extract */
  92.   UBYTE pad3;            /* 16 */
  93.   UBYTE pad4;            /* 17 */
  94.   ULONG Date;            /* 18 - Packed_Date */
  95.   ULONG DataCRC;        /* 22 (little endian) */
  96.   ULONG HeaderCRC;        /* 26 (little endian) */
  97.   UBYTE FilenameSize;        /* 30 - filename length */
  98. }; /* SIZE = 31 */
  99.  
  100. /* Header CRC includes filename and comment. */
  101.  
  102. #define LZXHEADERSIZE    31
  103.  
  104. /* Packed date [4 BYTES, bit 0 is MSB, 31 is LSB]
  105.   bit  0 -  4    Day
  106.        5 -  8    Month    (January is 0)
  107.        9 - 14    Year    (start 1970)
  108.       15 - 19    Hour
  109.       20 - 25    Minute
  110.       26 - 31    Second
  111. */
  112.  
  113. struct LZXEntryData {
  114.   ULONG CRC;        /* CRC of uncrunched data */
  115.   ULONG PackMode;    /* CrunchMode */
  116.   ULONG ArchivePos;    /* Position is source file */
  117.   ULONG DataStart;    /* Position in merged buffer */
  118. };
  119.  
  120. #define LZXPE(a)    ((struct LZXEntryData *) ((a)->xfi_PrivateInfo))
  121. #define LZXDD(a)    ((struct LZXDecrData *) ((a)->xai_PrivateClient))
  122. struct LZXDecrData {
  123.   ULONG ArchivePos;    /* The Archive-Pos to detect if it is correct buffer */
  124.   ULONG DataPos;    /* must be lower or equal to current entry or reinit is necessary */
  125.  
  126.   UBYTE *source;
  127.   UBYTE *destination;
  128.   UBYTE *source_end;
  129.   UBYTE *destination_end;
  130.   UBYTE *pos;
  131.  
  132.   ULONG decrunch_method;
  133.   ULONG decrunch_length;
  134.   ULONG pack_size;
  135.   ULONG last_offset;
  136.   ULONG control;
  137.   LONG  shift;
  138.  
  139.   UBYTE offset_len[8];
  140.   UWORD offset_table[128];
  141.   UBYTE huffman20_len[20];
  142.   UWORD huffman20_table[96];
  143.   UBYTE literal_len[768];
  144.   UWORD literal_table[5120];
  145.  
  146.   UBYTE read_buffer[16384];        /* have a reasonable sized read buffer */
  147.   UBYTE decrunch_buffer[258+65536+258];    /* allow overrun for speed */
  148. };
  149.  
  150. ASM(BOOL) LZX_RecogData(REG(d0, ULONG size), REG(a0, STRPTR data),
  151. REG(a6, struct xadMasterBase *xadMasterBase))
  152. { CPUCHECK
  153.   if(data[0] == 'L' && data[1] == 'Z' && data[2] == 'X')
  154.     return 1;
  155.   else
  156.     return 0;
  157. }
  158.  
  159. ASM(LONG) LZX_GetInfo(REG(a0, struct xadArchiveInfo *ai),
  160. REG(a6, struct xadMasterBase *xadMasterBase))
  161. {
  162.   LONG err, num = 1;
  163.   ULONG bufpos = 0;
  164.   struct xadFileInfo *fi = 0, *fi2, *fig = 0; /* fig - first grouped ptr */
  165.   struct LZXArc_Header head;
  166.  
  167.   if(!(err = xadHookAccess(XADAC_INPUTSEEK, sizeof(struct LZXInfo_Header), 0, ai)))
  168.   {
  169.     while(!err && ai->xai_InPos < ai->xai_InSize)
  170.     {
  171.       if(!(err = xadHookAccess(XADAC_READ, LZXHEADERSIZE, &head, ai)))
  172.       {
  173.     ULONG i, j, k, l, crc;
  174.         i = head.CommentSize;
  175.         j = head.FilenameSize;
  176.         k = EndConvI32(head.HeaderCRC);
  177.         head.HeaderCRC = 0; /* clear for CRC check */
  178.  
  179.         if(!(fi2 = (struct xadFileInfo *) xadAllocObject(XADOBJ_FILEINFO,
  180.         XAD_OBJNAMESIZE, j+1, i ? XAD_OBJCOMMENTSIZE : TAG_IGNORE, i+1,
  181.         XAD_OBJPRIVINFOSIZE, sizeof(struct LZXEntryData), TAG_DONE)))
  182.           err = XADERR_NOMEMORY;
  183.         else if(!(err = xadHookAccess(XADAC_READ, j, fi2->xfi_FileName, ai)) &&
  184.         (!i || !(err = xadHookAccess(XADAC_READ, i, fi2->xfi_Comment, ai))))
  185.         {
  186.           l = EndConvI32(head.CrSize);
  187.  
  188.           if(!l || !(err = xadHookAccess(XADAC_INPUTSEEK, l, 0, ai)))
  189.           {
  190.             crc = xadCalcCRC32(XADCRC32_ID1, ~0, LZXHEADERSIZE, (STRPTR) &head);
  191.             crc = xadCalcCRC32(XADCRC32_ID1, crc, j, fi2->xfi_FileName);
  192.             if(i)
  193.               crc = xadCalcCRC32(XADCRC32_ID1, crc, i, fi2->xfi_Comment);
  194.  
  195.             if(~crc != k)
  196.               err = XADERR_CHECKSUM;
  197.             else
  198.             {
  199.               if(!fig)
  200.               {
  201.                 fig = fi2; bufpos = 0;
  202.               }
  203.           fi2->xfi_Size = EndConvI32(head.FileSize);
  204.           fi2->xfi_EntryNumber = num++;
  205.           if(!l && !fi2->xfi_Size && fi2->xfi_FileName[--j] == '/')
  206.           {
  207.             fi2->xfi_FileName[j] = 0;
  208.             fi2->xfi_Flags |= XADFIF_DIRECTORY;
  209.           }
  210.  
  211.           i = head.Attributes;
  212.           j = 0;
  213.  
  214.           if(!(i & LZXHDR_PROT_READ))
  215.             j |= FIBF_READ;
  216.           if(!(i & LZXHDR_PROT_WRITE))
  217.             j |= FIBF_WRITE;
  218.           if(!(i & LZXHDR_PROT_DELETE))
  219.             j |= FIBF_DELETE;
  220.           if(!(i & LZXHDR_PROT_EXECUTE))
  221.             j |= FIBF_EXECUTE;
  222.           j |= (i & (LZXHDR_PROT_ARCHIVE|LZXHDR_PROT_SCRIPT));
  223.           if(i & LZXHDR_PROT_PURE)
  224.             j |= FIBF_PURE;
  225.           if(i & LZXHDR_PROT_HOLD)
  226.             j |= (1<<7);    /* not defined in <dos/dos.h> */
  227.           fi2->xfi_Protection = j;
  228.  
  229.           { /* Make the date */
  230.             struct xadDate d;
  231.             j = head.Date;
  232.             d.xd_Second = j & 63;
  233.             j >>= 6;
  234.             d.xd_Minute = j & 63;
  235.             j >>= 6;
  236.             d.xd_Hour = j & 31;
  237.             j >>= 5;
  238.             d.xd_Year = 1970 + (j & 63);
  239.             j >>= 6;
  240.             d.xd_Month = 1 + (j & 15);
  241.             j >>= 4;
  242.             d.xd_Day = j;
  243.             d.xd_Micros = 0;
  244.                 xadConvertDates(XAD_DATEXADDATE, &d, XAD_GETDATEXADDATE,
  245.                 &fi2->xfi_Date, TAG_DONE);
  246.           }
  247.           LZXPE(fi2)->CRC = EndConvI32(head.DataCRC);
  248.           LZXPE(fi2)->DataStart = bufpos;
  249.           bufpos += fi2->xfi_Size;
  250.           if(head.Flags & LZXHDR_FLAG_MERGED)
  251.           {
  252.             fi2->xfi_Flags |= XADFIF_GROUPED;
  253.             if(l)
  254.             {
  255.               fi2->xfi_Flags |= XADFIF_ENDOFGROUP;
  256.               fi2->xfi_GroupCrSize = l;
  257.             }
  258.           }
  259.           else
  260.             fi2->xfi_CrunchSize = l;
  261.           
  262.           if(l)
  263.           {
  264.             LZXPE(fi2)->ArchivePos = ai->xai_InPos-l;
  265.             LZXPE(fi2)->PackMode = head.PackMode;
  266.             while(fig)
  267.             {
  268.               fig->xfi_GroupCrSize = l;
  269.               LZXPE(fig)->ArchivePos = ai->xai_InPos-l;
  270.               LZXPE(fig)->PackMode = head.PackMode;
  271.                   fig = fig->xfi_Next;
  272.                 }
  273.               }
  274.  
  275.               if(!fi)
  276.                 ai->xai_FileInfo = fi2;
  277.               else
  278.                 fi->xfi_Next = fi2;
  279.               fi = fi2;
  280.               fi2 = 0;
  281.             } /* skip crunched data */
  282.           } /* get filename and comment */
  283.           if(fi2)
  284.             xadFreeObjectA(fi2,0);
  285.         } /* xadFileInfo Allocation */
  286.       } /* READ header */
  287.     } /* while loop */
  288.   } /* INPUTSEEK 3 bytes */
  289.  
  290.   if(err && ai->xai_FileInfo)
  291.   {
  292.     ai->xai_Flags |= XADAIF_FILECORRUPT;
  293.     ai->xai_LastError = err;
  294.     err = 0;
  295.   }
  296.  
  297.   return err;
  298. }
  299.  
  300. /* ---------------------------------------------------------------------- */
  301.  
  302. static const UBYTE LZXtable_one[32] = {
  303.   0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14
  304. };
  305.  
  306. static const ULONG LZXtable_two[32] = {
  307.   0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,
  308.   1536,2048,3072,4096,6144,8192,12288,16384,24576,32768,49152,
  309. };
  310.  
  311. static const UWORD LZXmask_bits[16] = {
  312.   0x0000,0x0001,0x0003,0x0007,0x000F,0x001F,0x003F,0x007F,
  313.   0x00FF,0x01FF,0x03FF,0x07FF,0x0FFF,0x1FFF,0x3FFF,0x7FFF,
  314. };
  315.  
  316. static const UBYTE LZXtable_four[34] = {
  317.   0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
  318.   0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
  319. };
  320.  
  321. /* ---------------------------------------------------------------------- */
  322.  
  323. /* Build a fast huffman decode table from the symbol bit lengths.         */
  324. /* There is an alternate algorithm which is faster but also more complex. */
  325.  
  326. static LONG LZXmake_decode_table(LONG number_symbols, LONG LZXtable_size,
  327.                       UBYTE *length, unsigned short *table)
  328. {
  329.  register UBYTE bit_num = 0;
  330.  register LONG symbol;
  331.  ULONG leaf; /* could be a register */
  332.  ULONG LZXtable_mask, bit_mask, pos, fill, next_symbol, reverse;
  333.  LONG abort = 0;
  334.  
  335.  pos = 0; /* consistantly used as the current position in the decode table */
  336.  
  337.  bit_mask = LZXtable_mask = 1 << LZXtable_size;
  338.  
  339.  bit_mask >>= 1; /* don't do the first number */
  340.  bit_num++;
  341.  
  342.  while((!abort) && (bit_num <= LZXtable_size))
  343.  {
  344.   for(symbol = 0; symbol < number_symbols; symbol++)
  345.   {
  346.    if(length[symbol] == bit_num)
  347.    {
  348.     reverse = pos; /* reverse the order of the position's bits */
  349.     leaf = 0;
  350.     fill = LZXtable_size;
  351.     do /* reverse the position */
  352.     {
  353.      leaf = (leaf << 1) + (reverse & 1);
  354.      reverse >>= 1;
  355.     } while(--fill);
  356.     if((pos += bit_mask) > LZXtable_mask)
  357.     {
  358.      abort = 1;
  359.      break; /* we will overrun the table! abort! */
  360.     }
  361.     fill = bit_mask;
  362.     next_symbol = 1 << bit_num;
  363.     do
  364.     {
  365.      table[leaf] = symbol;
  366.      leaf += next_symbol;
  367.     } while(--fill);
  368.    }
  369.   }
  370.   bit_mask >>= 1;
  371.   bit_num++;
  372.  }
  373.  
  374.  if((!abort) && (pos != LZXtable_mask))
  375.  {
  376.   for(symbol = pos; symbol < LZXtable_mask; symbol++) /* clear the rest of the table */
  377.   {
  378.    reverse = symbol; /* reverse the order of the position's bits */
  379.    leaf = 0;
  380.    fill = LZXtable_size;
  381.    do /* reverse the position */
  382.    {
  383.     leaf = (leaf << 1) + (reverse & 1);
  384.     reverse >>= 1;
  385.    } while(--fill);
  386.    table[leaf] = 0;
  387.   }
  388.   next_symbol = LZXtable_mask >> 1;
  389.   pos <<= 16;
  390.   LZXtable_mask <<= 16;
  391.   bit_mask = 32768;
  392.  
  393.   while((!abort) && (bit_num <= 16))
  394.   {
  395.    for(symbol = 0; symbol < number_symbols; symbol++)
  396.    {
  397.     if(length[symbol] == bit_num)
  398.     {
  399.      reverse = pos >> 16; /* reverse the order of the position's bits */
  400.      leaf = 0;
  401.      fill = LZXtable_size;
  402.      do /* reverse the position */
  403.      {
  404.       leaf = (leaf << 1) + (reverse & 1);
  405.       reverse >>= 1;
  406.      } while(--fill);
  407.      for(fill = 0; fill < bit_num - LZXtable_size; fill++)
  408.      {
  409.       if(table[leaf] == 0)
  410.       {
  411.        table[(next_symbol << 1)] = 0;
  412.        table[(next_symbol << 1) + 1] = 0;
  413.        table[leaf] = next_symbol++;
  414.       }
  415.       leaf = table[leaf] << 1;
  416.       leaf += (pos >> (15 - fill)) & 1;
  417.      }
  418.      table[leaf] = symbol;
  419.      if((pos += bit_mask) > LZXtable_mask)
  420.      {
  421.       abort = 1;
  422.       break; /* we will overrun the table! abort! */
  423.      }
  424.     }
  425.    }
  426.    bit_mask >>= 1;
  427.    bit_num++;
  428.   }
  429.  }
  430.  if(pos != LZXtable_mask) abort = 1; /* the table is incomplete! */
  431.  
  432.  return(abort);
  433. }
  434.  
  435. /* ---------------------------------------------------------------------- */
  436. /* Read and build the decrunch tables. There better be enough data in the */
  437. /* source buffer or it's stuffed. */
  438.  
  439. static LONG LZX_read_literal_table(struct LZXDecrData *decr)
  440. {
  441.  register ULONG control;
  442.  register LONG shift;
  443.  ULONG temp; /* could be a register */
  444.  ULONG symbol, pos, count, fix, max_symbol;
  445.  UBYTE *source;
  446.  LONG abort = 0;
  447.  
  448.  source = decr->source;
  449.  control = decr->control;
  450.  shift = decr->shift;
  451.  
  452.  if(shift < 0) /* fix the control word if necessary */
  453.  {
  454.   shift += 16;
  455.   control += *source++ << (8 + shift);
  456.   control += *source++ << shift;
  457.  }
  458.  
  459. /* read the decrunch method */
  460.  
  461.  decr->decrunch_method = control & 7;
  462.  control >>= 3;
  463.  if((shift -= 3) < 0)
  464.  {
  465.   shift += 16;
  466.   control += *source++ << (8 + shift);
  467.   control += *source++ << shift;
  468.  }
  469.  
  470. /* Read and build the offset huffman table */
  471.  
  472.  if((!abort) && (decr->decrunch_method == 3))
  473.  {
  474.   for(temp = 0; temp < 8; temp++)
  475.   {
  476.    decr->offset_len[temp] = control & 7;
  477.    control >>= 3;
  478.    if((shift -= 3) < 0)
  479.    {
  480.     shift += 16;
  481.     control += *source++ << (8 + shift);
  482.     control += *source++ << shift;
  483.    }
  484.   }
  485.   abort = LZXmake_decode_table(8, 7, decr->offset_len, decr->offset_table);
  486.  }
  487.  
  488. /* read decrunch length */
  489.  
  490.  if(!abort)
  491.  {
  492.   decr->decrunch_length = (control & 255) << 16;
  493.   control >>= 8;
  494.   if((shift -= 8) < 0)
  495.   {
  496.    shift += 16;
  497.    control += *source++ << (8 + shift);
  498.    control += *source++ << shift;
  499.   }
  500.   decr->decrunch_length += (control & 255) << 8;
  501.   control >>= 8;
  502.   if((shift -= 8) < 0)
  503.   {
  504.    shift += 16;
  505.    control += *source++ << (8 + shift);
  506.    control += *source++ << shift;
  507.   }
  508.   decr->decrunch_length += (control & 255);
  509.   control >>= 8;
  510.   if((shift -= 8) < 0)
  511.   {
  512.    shift += 16;
  513.    control += *source++ << (8 + shift);
  514.    control += *source++ << shift;
  515.   }
  516.  }
  517.  
  518. /* read and build the huffman literal table */
  519.  
  520.  if((!abort) && (decr->decrunch_method != 1))
  521.  {
  522.   pos = 0;
  523.   fix = 1;
  524.   max_symbol = 256;
  525.  
  526.   do
  527.   {
  528.    for(temp = 0; temp < 20; temp++)
  529.    {
  530.     decr->huffman20_len[temp] = control & 15;
  531.     control >>= 4;
  532.     if((shift -= 4) < 0)
  533.     {
  534.      shift += 16;
  535.      control += *source++ << (8 + shift);
  536.      control += *source++ << shift;
  537.     }
  538.    }
  539.    abort = LZXmake_decode_table(20, 6, decr->huffman20_len, decr->huffman20_table);
  540.  
  541.    if(abort) break; /* argh! table is corrupt! */
  542.  
  543.    do
  544.    {
  545.     if((symbol = decr->huffman20_table[control & 63]) >= 20)
  546.     {
  547.      do /* symbol is longer than 6 bits */
  548.      {
  549.       symbol = decr->huffman20_table[((control >> 6) & 1) + (symbol << 1)];
  550.       if(!shift--)
  551.       {
  552.        shift += 16;
  553.        control += *source++ << 24;
  554.        control += *source++ << 16;
  555.       }
  556.       control >>= 1;
  557.      } while(symbol >= 20);
  558.      temp = 6;
  559.     }
  560.     else
  561.     {
  562.      temp = decr->huffman20_len[symbol];
  563.     }
  564.     control >>= temp;
  565.     if((shift -= temp) < 0)
  566.     {
  567.      shift += 16;
  568.      control += *source++ << (8 + shift);
  569.      control += *source++ << shift;
  570.     }
  571.     switch(symbol)
  572.     {
  573.      case 17:
  574.      case 18:
  575.      {
  576.       if(symbol == 17)
  577.       {
  578.        temp = 4;
  579.        count = 3;
  580.       }
  581.       else /* symbol == 18 */
  582.       {
  583.        temp = 6 - fix;
  584.        count = 19;
  585.       }
  586.       count += (control & LZXmask_bits[temp]) + fix;
  587.       control >>= temp;
  588.       if((shift -= temp) < 0)
  589.       {
  590.        shift += 16;
  591.        control += *source++ << (8 + shift);
  592.        control += *source++ << shift;
  593.       }
  594.       while((pos < max_symbol) && (count--))
  595.        decr->literal_len[pos++] = 0;
  596.       break;
  597.      }
  598.      case 19:
  599.      {
  600.       count = (control & 1) + 3 + fix;
  601.       if(!shift--)
  602.       {
  603.        shift += 16;
  604.        control += *source++ << 24;
  605.        control += *source++ << 16;
  606.       }
  607.       control >>= 1;
  608.       if((symbol = decr->huffman20_table[control & 63]) >= 20)
  609.       {
  610.        do /* symbol is longer than 6 bits */
  611.        {
  612.         symbol = decr->huffman20_table[((control >> 6) & 1) + (symbol << 1)];
  613.         if(!shift--)
  614.         {
  615.          shift += 16;
  616.          control += *source++ << 24;
  617.          control += *source++ << 16;
  618.         }
  619.         control >>= 1;
  620.        } while(symbol >= 20);
  621.        temp = 6;
  622.       }
  623.       else
  624.       {
  625.        temp = decr->huffman20_len[symbol];
  626.       }
  627.       control >>= temp;
  628.       if((shift -= temp) < 0)
  629.       {
  630.        shift += 16;
  631.        control += *source++ << (8 + shift);
  632.        control += *source++ << shift;
  633.       }
  634.       symbol = LZXtable_four[decr->literal_len[pos] + 17 - symbol];
  635.       while((pos < max_symbol) && (count--))
  636.        decr->literal_len[pos++] = symbol;
  637.       break;
  638.      }
  639.      default:
  640.      {
  641.       symbol = LZXtable_four[decr->literal_len[pos] + 17 - symbol];
  642.       decr->literal_len[pos++] = symbol;
  643.       break;
  644.      }
  645.     }
  646.    } while(pos < max_symbol);
  647.    fix--;
  648.    max_symbol += 512;
  649.   } while(max_symbol == 768);
  650.  
  651.   if(!abort)
  652.    abort = LZXmake_decode_table(768, 12, decr->literal_len, decr->literal_table);
  653.  }
  654.  
  655.  decr->control = control;
  656.  decr->shift = shift;
  657.  decr->source = source;
  658.  return(abort);
  659. }
  660.  
  661. /* ---------------------------------------------------------------------- */
  662.  
  663. /* Fill up the decrunch buffer. Needs lots of overrun for both destination */
  664. /* and source buffers. Most of the time is spent in this routine so it's  */
  665. /* pretty damn optimized. */
  666. static void LZXdecrunch(struct LZXDecrData *decr)
  667. {
  668.  register ULONG control;
  669.  register LONG shift;
  670.  ULONG temp; /* could be a register */
  671.  ULONG symbol, count;
  672.  UBYTE *string, *source, *destination;
  673.  
  674.  control = decr->control;
  675.  shift = decr->shift;
  676.  source = decr->source;
  677.  destination = decr->destination;
  678.  
  679.  do
  680.  {
  681.   if((symbol = decr->literal_table[control & 4095]) >= 768)
  682.   {
  683.    control >>= 12;
  684.    if((shift -= 12) < 0)
  685.    {
  686.     shift += 16;
  687.     control += *source++ << (8 + shift);
  688.     control += *source++ << shift;
  689.    }
  690.    do /* literal is longer than 12 bits */
  691.    {
  692.     symbol = decr->literal_table[(control & 1) + (symbol << 1)];
  693.     if(!shift--)
  694.     {
  695.      shift += 16;
  696.      control += *source++ << 24;
  697.      control += *source++ << 16;
  698.     }
  699.     control >>= 1;
  700.    } while(symbol >= 768);
  701.   }
  702.   else
  703.   {
  704.    temp = decr->literal_len[symbol];
  705.    control >>= temp;
  706.    if((shift -= temp) < 0)
  707.    {
  708.     shift += 16;
  709.     control += *source++ << (8 + shift);
  710.     control += *source++ << shift;
  711.    }
  712.   }
  713.   if(symbol < 256)
  714.   {
  715.    *destination++ = symbol;
  716.   }
  717.   else
  718.   {
  719.    symbol -= 256;
  720.    count = LZXtable_two[temp = symbol & 31];
  721.    temp = LZXtable_one[temp];
  722.    if((temp >= 3) && (decr->decrunch_method == 3))
  723.    {
  724.     temp -= 3;
  725.     count += ((control & LZXmask_bits[temp]) << 3);
  726.     control >>= temp;
  727.     if((shift -= temp) < 0)
  728.     {
  729.      shift += 16;
  730.      control += *source++ << (8 + shift);
  731.      control += *source++ << shift;
  732.     }
  733.     count += (temp = decr->offset_table[control & 127]);
  734.     temp = decr->offset_len[temp];
  735.    }
  736.    else
  737.    {
  738.     count += control & LZXmask_bits[temp];
  739.     if(!count) count = decr->last_offset;
  740.    }
  741.    control >>= temp;
  742.    if((shift -= temp) < 0)
  743.    {
  744.     shift += 16;
  745.     control += *source++ << (8 + shift);
  746.     control += *source++ << shift;
  747.    }
  748.    decr->last_offset = count;
  749.  
  750.    count = LZXtable_two[temp = (symbol >> 5) & 15] + 3;
  751.    temp = LZXtable_one[temp];
  752.    count += (control & LZXmask_bits[temp]);
  753.    control >>= temp;
  754.    if((shift -= temp) < 0)
  755.    {
  756.     shift += 16;
  757.     control += *source++ << (8 + shift);
  758.     control += *source++ << shift;
  759.    }
  760.    string = (decr->decrunch_buffer + decr->last_offset < destination) ?
  761.             destination - decr->last_offset : destination + 65536 - decr->last_offset;
  762.    do
  763.    {
  764.     *destination++ = *string++;
  765.    } while(--count);
  766.   }
  767.  } while((destination < decr->destination_end) && (source < decr->source_end));
  768.  
  769.  decr->control = control;
  770.  decr->shift = shift;
  771.  decr->source = source;
  772.  decr->destination = destination;
  773. }
  774.  
  775. /* ---------------------------------------------------------------------- */
  776.  
  777. static LONG LZXextract(struct xadArchiveInfo *ai, struct xadMasterBase *xadMasterBase,
  778. ULONG unpack_size, ULONG rescrc)
  779. {
  780.   UBYTE *temp;
  781.   ULONG count, crc = ~0;
  782.   LONG err;
  783.   struct LZXDecrData *decr;
  784.  
  785.   decr = (struct LZXDecrData *) ai->xai_PrivateClient;
  786.  
  787.   while(unpack_size > 0)
  788.   {
  789.     if(decr->pos == decr->destination) /* time to fill the buffer? */
  790.     {
  791.       /* check if we have enough data and read some if not */
  792.       if(decr->source >= decr->source_end) /* have we exhausted the current read buffer? */
  793.       {
  794.         temp = decr->read_buffer;
  795.         if((count = temp - decr->source + 16384))
  796.         {
  797.           do /* copy the remaining overrun to the start of the buffer */
  798.           {
  799.             *temp++ = *(decr->source++);
  800.           } while(--count);
  801.         }
  802.         decr->source = decr->read_buffer;
  803.         count = decr->source - temp + 16384;
  804.  
  805.         if(decr->pack_size < count)
  806.           count = decr->pack_size; /* make sure we don't read too much */
  807.  
  808.         if((err = xadHookAccess(XADAC_READ, count, temp, ai)))
  809.           return err;
  810.         decr->pack_size -= count;
  811.  
  812.         temp += count;
  813.         if(decr->source >= temp)
  814.           return XADERR_DECRUNCH; /* argh! no more data! */
  815.       } /* if(decr->source >= decr->source_end) */
  816.  
  817.     /* check if we need to read the tables */
  818.     if(decr->decrunch_length <= 0)
  819.     {
  820.       if(LZX_read_literal_table(decr))
  821.         return XADERR_DECRUNCH; /* argh! can't make huffman tables! */
  822.     }
  823.  
  824.     /* unpack some data */
  825.     if(decr->destination >= decr->decrunch_buffer + 258 + 65536)
  826.     {
  827.       if((count = decr->destination - decr->decrunch_buffer - 65536))
  828.       {
  829.         temp = (decr->destination = decr->decrunch_buffer) + 65536;
  830.         do /* copy the overrun to the start of the buffer */
  831.         {
  832.           *(decr->destination++) = *temp++;
  833.         } while(--count);
  834.       }
  835.       decr->pos = decr->destination;
  836.     }
  837.     decr->destination_end = decr->destination + decr->decrunch_length;
  838.     if(decr->destination_end > decr->decrunch_buffer + 258 + 65536)
  839.       decr->destination_end = decr->decrunch_buffer + 258 + 65536;
  840.     temp = decr->destination;
  841.  
  842.     LZXdecrunch(decr);
  843.  
  844.     decr->decrunch_length -= (decr->destination - temp);
  845.    }
  846.  
  847. /* calculate amount of data we can use before we need to fill the buffer again */
  848.    count = decr->destination - decr->pos;
  849.    if(count > unpack_size)
  850.      count = unpack_size; /* take only what we need */
  851.  
  852.    if(rescrc) /* when no CRC given, then skip writing */
  853.    {
  854.      crc = xadCalcCRC32(XADCRC32_ID1, crc, count, decr->pos);
  855.      if((err = xadHookAccess(XADAC_WRITE, count, decr->pos, ai)))
  856.        return err;
  857.    }
  858.    unpack_size -= count;
  859.    decr->pos += count;
  860.    decr->DataPos += count;
  861.  }
  862.  
  863.  if(rescrc && ~crc != rescrc)
  864.    return XADERR_CHECKSUM;
  865.  
  866.  return 0;
  867. }
  868.  
  869. /* ---------------------------------------------------------------------- */
  870.  
  871. ASM(LONG) LZX_UnArchive(REG(a0, struct xadArchiveInfo *ai),
  872. REG(a6, struct xadMasterBase *xadMasterBase))
  873. {
  874.   struct xadFileInfo *fi;
  875.   struct LZXDecrData *decr = 0;
  876.   LONG ret = 0, i;
  877.   ULONG crc = ~0;
  878.  
  879.   fi = ai->xai_CurFile;
  880.   if(!ai->xai_PrivateClient || LZXDD(ai)->ArchivePos != LZXPE(fi)->ArchivePos
  881.   || LZXDD(ai)->DataPos > LZXPE(fi)->DataStart)
  882.   {
  883.     if(ai->xai_PrivateClient) /* free the unneeded data */
  884.     {
  885.       xadFreeObjectA(ai->xai_PrivateClient, 0);
  886.       ai->xai_PrivateClient = 0;
  887.     }
  888.     if((i = LZXPE(fi)->ArchivePos - ai->xai_InPos))
  889.     {
  890.       if((ret = xadHookAccess(XADAC_INPUTSEEK, i, 0, ai)))
  891.         return ret;
  892.     }
  893.   }
  894.  
  895.   switch(LZXPE(fi)->PackMode)
  896.   {
  897.   case LZXHDR_PACK_STORE:
  898.     if(!(ret = xadHookTagAccess(XADAC_COPY, fi->xfi_Size, 0, ai, XAD_GETCRC32, &crc, TAG_DONE)) && ~crc != LZXPE(fi)->CRC)
  899.       ret = XADERR_CHECKSUM;
  900.     break;
  901.   case LZXHDR_PACK_NORMAL:
  902.     if(!ai->xai_PrivateClient && !(decr = (struct LZXDecrData *)
  903.     xadAllocVec(sizeof(struct LZXDecrData), MEMF_PUBLIC|MEMF_CLEAR)))
  904.       ret = XADERR_NOMEMORY;
  905.     else
  906.     {
  907.       if(decr)
  908.       {
  909.         decr->ArchivePos = LZXPE(fi)->ArchivePos;
  910.         decr->DataPos = 0;
  911.         decr->shift = -16;
  912.         decr->last_offset = 1;
  913.         decr->source_end = (decr->source = decr->read_buffer + 16384) - 1024;
  914.         decr->pos = decr->destination_end = decr->destination = decr->decrunch_buffer + 258 + 65536;
  915.         decr->pack_size = fi->xfi_Flags & XADFIF_GROUPED ?
  916.         fi->xfi_GroupCrSize : fi->xfi_CrunchSize;
  917.         ai->xai_PrivateClient = decr;
  918.       }
  919.  
  920.       if((i = LZXPE(fi)->DataStart - LZXDD(ai)->DataPos))
  921.     ret = LZXextract(ai, xadMasterBase, i, 0);
  922.     
  923.       if(!ret)
  924.     ret = LZXextract(ai, xadMasterBase, fi->xfi_Size, LZXPE(fi)->CRC);
  925.  
  926.       /* free no longer needed temporary buffer and stuff structure */
  927.       if(ret || !(fi->xfi_Flags & XADFIF_GROUPED) || (fi->xfi_Flags & XADFIF_ENDOFGROUP))
  928.       {
  929.         xadFreeObjectA(ai->xai_PrivateClient, 0);
  930.         ai->xai_PrivateClient = 0;
  931.       }
  932.     }
  933.     break;
  934.   default: ret = XADERR_DECRUNCH; break;
  935.   }
  936.  
  937.   return ret;
  938. }
  939.  
  940. ASM(void) LZX_Free(REG(a0, struct xadArchiveInfo *ai),
  941. REG(a6, struct xadMasterBase *xadMasterBase))
  942. {
  943.   if(ai->xai_PrivateClient) /* decrunch buffer */
  944.   {
  945.     xadFreeObjectA(ai->xai_PrivateClient, 0);
  946.     ai->xai_PrivateClient = 0;
  947.   }
  948. }
  949.  
  950. const struct xadClient LZX_Client = {
  951. NEXTCLIENT, XADCLIENT_VERSION, XADMASTERVERSION, LZX_VERSION, LZX_REVISION,
  952. 10, XADCF_FILEARCHIVER|XADCF_FREEFILEINFO, XADCID_LZX, "LZX",
  953. (BOOL (*)()) LZX_RecogData, (LONG (*)()) LZX_GetInfo,
  954. (LONG (*)()) LZX_UnArchive, (void (*)()) LZX_Free};
  955.  
  956. #endif /* XADMASTER_LZX_C */
  957.